/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testings;

import java.awt.Color;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.AbstractRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.statistics.HistogramDataset;
import org.jfree.data.statistics.HistogramType;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.RefineryUtilities;
import org.jfree.util.ShapeUtilities;
import weka.core.Instance;
import weka.core.Instances;

/**
 * Used to graph data (scatterplot) from either an Instances object, or an double[][]  
 * array. 2D graph, using x and y plots, or histogram
 * @author Agnitto
 */
public class GraphIt {

    boolean histo = false;
    XYSeriesCollection data = new XYSeriesCollection();
    private XYSeries series = new XYSeries("All points");
    private XYSeries outseries = new XYSeries("Outlier points (OF >= 2.0)");
    private XYSeries outseries2 = new XYSeries("Outlier points (OF >= 4.0)");
    private XYSeries outseries3 = new XYSeries("Outlier points (OF >= 8.0)");

    HistogramDataset dataset = new HistogramDataset();
    private String graphtitle = "Your data";
    JFreeChart chart = null;
    boolean outliers; 
    int[] xy;

    /**
     * You call this to make your graph. Make sure you use addToSeries() methods
     * below first to add data. 
     */
    public void initateGraphing() {
        XYSeriesDemo demo = new XYSeriesDemo("Your graph");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }

    /**
     * Changes the title of the graph
     * @param title 
     */
    public void changeTitle(String title) {
        this.graphtitle = title;
    }

    /**
     * Gets double values from a given instance. The two int values are the 
     * indexes of the values in the instance.
     * 
     * @param inst
     * @param first index, x value
     * @param second index, y value
     */
    public void addToSeries(Instances inst, int first, int second) {
        xy = new int[2];
        xy[0] = first;
        xy[1] = second;
         
        for (Instance getfrom : inst) {
            series.add(getfrom.value(first), getfrom.value(second));
        }
        data = new XYSeriesCollection(series);
    }

    /**
     * Creates histogram from single doubles from a set of instances. 
     * bars = how many bars you want to show. inst = set in instances. 
     * first = attribute to show.
     *
     * @param bars
     * @param inst
     * @param first 
     */
    public void addToSeries(int bars, Instances inst, int first) {
        double[] insts = new double[inst.size()];
        int i = 0;
        for (Instance getfrom : inst) {
            insts[i] = getfrom.value(first);
            i++;
        }
        dataset.setType(HistogramType.RELATIVE_FREQUENCY);
        dataset.addSeries("H1", insts, bars);
        histo = true;
    }

    /**
     * Takes double array of coordinates (x, y) and plots it
     * @param inst 
     */
    public void addToSeries(double[][] inst) {
        for (double[] point : inst) {
            series.add(point[0], point[1]);
        }
        data = new XYSeriesCollection(series);
    }

    /**
     * creates histogram from array of doubles. Bars = how many bars you want 
     * to show.
     * @param bars
     * @param inst
     * @return 
     */
    public void addToSeries(int bars, double[] inst) {
        dataset.setType(HistogramType.RELATIVE_FREQUENCY);
        dataset.addSeries("H1", inst, bars);
        histo = true;
    }

    /**
     * adds a set of outliers
     * 
     * @param outliers
     * @param inst 
     */
    public void addOutliers(int[] outliers, Instances inst) {
        this.outliers = true;
        for (int i = 0; i < outliers.length; i++) {
            outseries.add(inst.get(outliers[i]).value(xy[0]), inst.get(outliers[i]).value(xy[1]));
        }
        data.addSeries(outseries);
    }
    
    public void addOutliers2(int[] outliers, Instances inst) {
        this.outliers = true;
        for (int i = 0; i < outliers.length; i++) {
            outseries2.add(inst.get(outliers[i]).value(xy[0]), inst.get(outliers[i]).value(xy[1]));
        }
        data.addSeries(outseries2);
    }
    
    public void addOutliers3(int[] outliers, Instances inst) {
        this.outliers = true;
        for (int i = 0; i < outliers.length; i++) {
            outseries3.add(inst.get(outliers[i]).value(xy[0]), inst.get(outliers[i]).value(xy[1]));
        }
        data.addSeries(outseries3);
    }

    
    /**
     * Adds outliers as big black crosses behind a red dot
     */
    public void showOutliers() {
        if (chart != null) {

            Shape shape = ShapeUtilities.createDiagonalCross(3, 1);
           

       //     Shape shape2 = new Ellipse2D.Double(0, 0, 1, 1);

            XYPlot xyPlot = (XYPlot) chart.getPlot();
            xyPlot.setDomainCrosshairVisible(true);
            xyPlot.setRangeCrosshairVisible(true);
            AbstractRenderer renderer = (AbstractRenderer) xyPlot.getRenderer();
            renderer.setSeriesShape(1, shape);
            renderer.setSeriesShape(2, shape);
            renderer.setSeriesShape(3, shape);


         //   renderer.setSeriesShape(0, shape2);
            renderer.setSeriesPaint(1, Color.yellow);
            renderer.setSeriesPaint(2, Color.orange);
            renderer.setSeriesPaint(3, Color.red);

        }
    }

    private class XYSeriesDemo extends ApplicationFrame {

        public XYSeriesDemo(final String title) {

            super(title);
            createGraph();
        }

        public void createGraph() {

            if (!histo) {
                chart = ChartFactory.createScatterPlot(
                        graphtitle,
                        "X",
                        "Y",
                        data,
                        PlotOrientation.VERTICAL,
                        true,
                        true,
                        false);
                if (xy != null && xy.length > 0) {
                    showOutliers();
                }
            } else {
                chart = ChartFactory.createHistogram(
                        graphtitle,
                        "X",
                        "Y",
                        dataset,
                        PlotOrientation.VERTICAL,
                        true,
                        true,
                        false);
            }
            Shape shape2 = new Ellipse2D.Double(0, 0, 1, 1);
            XYPlot xyPlot = (XYPlot) chart.getPlot();
            xyPlot.setDomainCrosshairVisible(true);
            xyPlot.setRangeCrosshairVisible(true);
            AbstractRenderer renderer = (AbstractRenderer) xyPlot.getRenderer();
            renderer.setSeriesShape(0, shape2);
            renderer.setSeriesPaint(0, Color.black);
            LegendTitle legend = chart.getLegend();
            legend.setPosition(RectangleEdge.RIGHT);
            final ChartPanel chartPanel = new ChartPanel(chart);
            chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
            setContentPane(chartPanel);
        }
    }
}
